home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / varia / grammar2.lha / c++grammar2.0 / grammar5 / freegrm5.txt < prev    next >
Text File  |  1991-07-11  |  23KB  |  414 lines

  1. FILENAME: FREEGRAM5.TXT
  2. AUTHOR: Jim Roskind
  3.         Independent Consultant
  4.         516 Latania Palm Drive
  5.         Indialantic FL 32903
  6.         (407)729-4348
  7.         jar@hq.ileaf.com
  8.         or ...uunet!leafusa!jar
  9.  
  10.                                                         7/4/91
  11.  
  12. Dear C++ and C Grammar User,
  13.  
  14. I have written a YACC debugging tool, and a set of grammars for C  and 
  15. C++ in order to use them within my own personal project development. I 
  16. have  made  the  results  of  my  work in this area available to other 
  17. developers at no charge with the hope that they would use my work.   I 
  18. believe   the   entire   C++   community   can   benefit   from   such 
  19. standardization.  If any of the  copyright  notices  on  the  grammars 
  20. (which  are  VERY  liberal) prevent using my work, please notify me of 
  21. the problem.
  22.  
  23. Note that the grammars can each be processed by  YACC,  but  they  are 
  24. very clean, and make NO USE of the precedence setting (i.e.: %prec) or 
  25. associativity  setting (i.e.:%assoc) constructs of YACC.  This feature 
  26. should make them easily  portable  to  other  parser  generator  input 
  27. format.   This "cleanliness" fact also provides brutal exposure of all 
  28. the complex constructs in C++, and the complexity of the grammar as  a 
  29. whole  (the  C++  grammar  is  2 to 3 times as large as the C grammar) 
  30. reflects this exposure.
  31.  
  32. The files included in this set are:
  33.  
  34.     FREEGRM5.TXT    This introductory file
  35.     GRAMMAR5.TXT    Parsing ambiguities in C++, and in my grammar
  36.     CPP5.Y          My YACC compatible C++ grammar
  37.     C5.Y            My YACC compatible, ANSI C conformant grammar
  38.     CPP5.L          Flex input file defining a C++ lexical analyzer
  39.     SKELGRPH.C      A hacked file from the Berkeley YACC distribution
  40.     AUTODOC5.TXT    Documentation for my machine generated analysis
  41.     Y.OUTPUT        Machine generated analysis of the C++ grammar.
  42.  
  43. Aside from the addition of several files, this release of  my  grammar 
  44. corrects  a  few  problems  located  in my prior release.  I have also 
  45. transitioned to using names in my grammar that are more acceptable  to 
  46. a  wider  variety  of  parser  generators.  This release also includes 
  47. support for nested types (at  least  grammatically,  as  there  is  no 
  48. symbol  table  provided).  It does not support templates and exception 
  49. handling, as the ANSI C++ Committee  is  still  discussing  variations 
  50. (and  trying  to  deal  with a variety of ambiguities that the initial 
  51. proposals, such as what is described in the ARM, would entail).
  52.  
  53. Since my first public release of my grammar, I have received a  number 
  54. of  requests.   One  of  the  most  common  requests was for a lexical 
  55. analyzer to  go  with  the  grammar.   This  release  of  the  grammar 
  56. continues  to  provides  such  a a "bare bones" lexical analyzer.  The 
  57. analyzer does not support preprocessing, or even comment removal.   In 
  58. addition,  since  I  have  not  included  a  symbol table, or semantic 
  59. actions in the grammar  to  maintain  proper  context  (i.e.,  current 
  60. scope),   typedef  names  and  struct/class/union/enum  tags  are  not 
  61. *really* defined.  To  allow  users  to  experiment  with  my  grammar 
  62. without  a  symbol table, my lexer assumes that if the first letter of 
  63. the name is upper case, then then name is a type name.  This  hack  is 
  64. far  from  sufficient  for parsing full blown programs, but it is more 
  65. than sufficient for experimenting with the grammar  to  determine  the 
  66. acceptability  of  a  token sequence, and to understand how my grammar 
  67. parsed the sequence.
  68.  
  69. Since I did not  believe  that  a  lexical  analyzer  alone  would  be 
  70. sufficient  to assist many people with playing with my grammar, I have 
  71. also provided the basis for a tool to explain what a grammar is doing. 
  72. Specifically, I have modified a file that is included in the  Berkeley 
  73. YACC  distribution  so  that  parsers  generated  by such a YACC would 
  74. automatically display a syntax tree in graphical-ASCII format during a 
  75. parse.  The instructions for using and building  this  yacc  tool  are 
  76. presented  in  the  next  section.  Note that there are no significant 
  77. special hooks in my grammar or parser to excite this  yacc  tool,  and 
  78. the  tool can be used equally well on any grammar that you are working 
  79. with.  This graphical debugging tool  is  probably  one  of  the  most 
  80. popular  aspects  of  my  releases, and its presence and usefulness to 
  81. grammar developers should not be underestimated.
  82.  
  83. Significantly new to this  release  is  a  large  file  that  contains 
  84. machine  generated  documentation (re: Y.OUTPUT).  This file goes well 
  85. beyond what is provided in a typical verbose output, and provides both 
  86. detailed conflict analysis, and a  number  of  cross-references  which 
  87. make  it  **MUCH**  easier to read the associated grammar.  I have not 
  88. yet decided whether  to  market,  shareware,  or  plain  give-away  my 
  89. program,  so the best I can do at this point is to release the machine 
  90. generated documentation.  Unfortunately, this file  is  *very*  large, 
  91. and  I have decided (for the time being) to distribute it only via the 
  92. ftp sites only.  I am  doing  this  to  lessen  the  global  bandwidth 
  93. utilization  during my grammar posting to the network.  I will however 
  94. post the file (AUTODOC5.TXT)  which  documents  the  contents  of  the 
  95. Y.OUTPUT  file,  so that users can decide if they want to download the 
  96. larger  file.   To  hint  at  what  is  included  in   the   automatic 
  97. documentation, the following are the sections:
  98.  
  99.     Reference Grammar
  100.     Alphabetized Grammar
  101.     Sample Expansions for the Non-terminal Tokens
  102.     Summary Descriptions of the Terminal Tokens
  103.     Symbol and Grammar Cross Reference for the Tokens
  104.     Sample Stack Context and Accessing Sentences for each State
  105.     Concise list of Conflicts
  106.     Canonical Description of Conflicts
  107.     Verbose listing of state transitions
  108.     Explanations for all reductions suggested in conflicts
  109.  
  110. Please see AUTODOC5.TXT for more details.
  111.  
  112. I  have  posted  7  of  the  8 files to comp.lang.c++ (I will not post 
  113. Y.OUTPUT due to its size), to make this information  as  available  as 
  114. possible  to users and developers.  I will also post this introductory 
  115. note to comp.compilers, and comp.lang.c.  I am arranging for  archival 
  116. support  via  several  ftp  sites, and updates will be posted to those 
  117. sites.  I will also try to get the source to Berkeley YACC  posted  to 
  118. these  ftp  sites,  although it is certainly available at more central 
  119. sites.
  120.  
  121. Currently, Doug Lea and  Doug  Schmidtt  have  graciously  offered  to 
  122. provide  anonymous  ftp  sites  for  all  8  of  files, as well as the 
  123. Berkeley YACC source (if you need it).  The ftp addresses are:
  124.  
  125. ics.uci.edu (128.195.1.1) in the ftp/pub directory as:
  126.  
  127.     c++grammar2.0.tar.Z 
  128.     byacc1.8.tar.Z
  129.  
  130. mach1.npac.syr.edu (128.230.7.14) in the ftp/pub/C++ directory as:
  131.  
  132.     c++grammar2.0.tar.Z
  133.     byacc1.8.tar.z
  134.  
  135.  
  136.  
  137. HOW TO EXPERIMENT WITH THE C++ GRAMMAR
  138.  
  139. The following describes how to use the graphical debugging  extensions 
  140. to Berkeley YACC to explore the grammar.
  141.  
  142. Note that the following instructions assume that you have the Berkeley 
  143. YACC  source  on  hand.   You can actually use any YACC to process the 
  144. grammar, but  running  the  resulting  demo  (which  has  no  semantic 
  145. actions)  will  tend to be quite boring.  If you can't get hold of the 
  146. Berkeley YACC, you should  at  least  try  to  enable  the  "debugging 
  147. options"  in  your  parser  to  so  that  you can see in some way what 
  148. reductions are taking place.  (Hint: search for the letters "debug" in 
  149. the C file that your yacc produces...).
  150.  
  151.         1) Get the entire source for Berkeley YACC 1.8 1/2/91
  152.         2) Verify that you can make the YACC
  153.         3) Rename SKELETON.C to SKELOLD.C, and implant my SKELGRPH.C
  154.                 in that directory as SKELETON.C
  155.         4) Make the yacc using this new SKELETON.C
  156.         5) Using the above yacc, process my CPP5.Y file
  157.                 yacc -dvl cpp5.y
  158.            The result should be a file y.tab.c, and y.tab.h
  159.         6) Using Flex (replacement for lex) to process my CPP5.L file
  160.                 flex cpp5.l
  161.            the result should be yy.lex.c
  162.         7) Compile the two files
  163.                 cc -o cpp5  y.tab.c yy.lex.c
  164.            the result should be an executable called cpp5
  165.         8) Set the environment variable YYDEBUG to 6
  166.                 setenv YYDEBUG 6
  167.            If you don't do this, the graphical output will not appear!
  168.         9) Run the program cpp5
  169.                 cpp5
  170.         10) Try the input:
  171.                 int a;
  172.         11) You should see a nice parse tree.  Enjoy.  Note that
  173.             the lexer DOES NOT INCLUDE A SYMBOL TABLE, and does
  174.             NOT KEEP TRACK OF CURRENT SCOPES.  The hack (see the
  175.             CPP5.L file for details) is to assume that any identifier
  176.             that begins with a capital letter is a typedef name
  177.             Send complaints about code that doesn't parse "correctly".
  178.  
  179.  
  180.  
  181.  
  182. HISTORICAL NOTES
  183.  
  184.  
  185. Developing the C grammar (that is intended to be compatible  with  the 
  186. ANSI  C standard) was relatively straight forward (compared to the C++ 
  187. grammar).  The one difficulty in this process was the desire to  avoid 
  188. use  of  %prec  and  %assoc  constructs  in  YACC, which would tend to 
  189. obscure ambiguities.  Since I didn't know what ambiguities were  lying 
  190. in  wait  in  C++,  obscuring  ambiguities  was unacceptable.  It took 
  191. several weeks to remove the conflicts that typically appear,  and  the 
  192. tedious  process  exposed  several  ambiguities that are not currently 
  193. disambiguated by the ANSI standard.  The quality of the C  grammar  is 
  194. (IMHO)  dramatically  higher  than what has been made available within 
  195. the  public  domain.   Specifically,  a   C   grammar's   support   of 
  196. redefinition  of typedef names within inner scopes (the most difficult 
  197. area of the grammar) is typically excluded from public domain grammar, 
  198. and even excluded from most grammars that  are  supplied  commercially 
  199. with  parser  generators!   I  expect  that  this grammar will be very 
  200. useful in the development of C related tools.
  201.  
  202. The development of the C++ grammar (initially compatible with  version 
  203. 1.2,  but  enhanced to support version 2.0 specifications as they were 
  204. made available) was anything but straight  forward.   The  requirement 
  205. that  I  set  to NOT USE %prec and %assoc proved both a blessing and a 
  206. curse.  The blessing was that I could see what the  problems  were  in 
  207. the  language, the curse was that there were A LOT of conflicts (I can 
  208. recall  times  during  the  development  effort  when  the  number  of 
  209. conflicts  was  well  in  excess of 200).  The most recent addition of 
  210. nested types probably took about 2 weeks to implement.  On  the  other 
  211. hand,  I  probably  spent  several  months  developing  the  automated 
  212. documentation tools that allowed me to  debug  the  grammar  additions 
  213. this quickly. 
  214.  
  215. Towards  the  end of the initial development of the C++ grammar, which 
  216. took roughly 3 months of my time (circa summer 1989), I began  to  see 
  217. the  folly in part of my quest.  I came to the conclusion that further 
  218. attempts  to  modify  my  grammar,  so  as  to  defer  resolutions  of 
  219. ambiguities,  would  lead  to an unreadable language. Specifically, my 
  220. feeling was that I was  entering  into  a  battle  of  wits  with  the 
  221. compiler,  and  the compiler was starting to win.  It was beginning to 
  222. be the case that the parser COULD  figure  out  what  I  said,  but  I 
  223. couldn't.  Indeed, even examples in a version of the C++ 2.0 reference 
  224. manual (and published in the ARM) demonstrated this problem (my parser 
  225. could  parse  some  examples  that  neither  I  nor the authors parsed 
  226. correctly!).  At this point I decided to  stop  my  quest  to  FURTHER 
  227. defer  resolutions  of  ambiguities, and let the grammar commit in one 
  228. direction (always in favor of declarations), at the late point that is 
  229. provided by my grammar.  If this direction proved "incorrect in  light 
  230. of  the  context  that  followed", then I generated a syntax error.  I 
  231. believe this strategy provides  ample  room  for  expressiveness.   In 
  232. support  of  this expressiveness, I have (based on my discussions with 
  233. language  experts)  deferred  disambiguation  far  longer  than  other 
  234. attempts  at  producing an LR(1) grammar.  I would strongly argue that 
  235. any code that my grammar identifies as having a "syntax error"  (based 
  236. on  "premature"  disambiguation), but cfront allows, should ABSOLUTELY 
  237. be rewritten in a less ambiguous (and hence more portable) form.
  238.  
  239. It should be noted that my grammar cannot  be  in  constant  agreement 
  240. with   such  implementations  as  cfront  because  a)  my  grammar  is 
  241. internally consistent (mostly courtesy of its formal nature  and  YACC 
  242. verification),  and b) YACC generated parsers don't dump core. (I will 
  243. probably take a lot of flack for that last snipe, but.... every time I 
  244. have had difficulty figuring what  was  meant  syntactically  by  some 
  245. construct that the ARM was vague about, and I fed it to cfront, cfront 
  246. dumped core.)
  247.  
  248. One major motivation for using the C++ grammar that I have provided is 
  249. that it is capable of supporting old style function definitions (e.g.: 
  250. main(argc,  argv)  int  argc;  char*argv[];  {...}  ).  I believe this 
  251. capability was removed from the C++ specification in order  to  reduce 
  252. ambiguities  in  a  specific  implementation  (cfront).  As my grammar 
  253. demonstrates, this action was  not  necessary.  Supporting  old  style 
  254. function  definition  GREATLY  eases  the transition to the use of C++ 
  255. from traditional C.  I expect that as some parsers  begin  to  support 
  256. this  option,  that  other  parsing  engines  will  be  forced in this 
  257. direction by a competitive marketplace.  Using  my  grammar,  and  the 
  258. standards it implies, appears to be a very straightforward approach to 
  259. this support.
  260.  
  261. A  second  motivation for using my grammar is that it can be processed 
  262. by YACC.  The advantage in this fact lies with  YACC's  capability  to 
  263. identify  ambiguities.   For  software  manufacturers that are heavily 
  264. concerned with correctness,  this  is  an  INCREDIBLE  advantage.   My 
  265. experience  with  hand  written  parsers  (which  usually  represent a 
  266. translation by a fallible human from a grammar  to  parsing  code)  is 
  267. that  they  evolve and become more correct with time.  Ambiguous cases 
  268. are often misparsed, without the author ever  realizing  there  was  a 
  269. conflict!   In  contrast,  either  a  YACC  grammar  supports  a given 
  270. construct, or it doesn't.  If a YACC grammar supports a construct, the 
  271. semantic interpretation  is  usually  rather  straight  forward.   The 
  272. likelihood of internal errors in the parser is therefore SIGNIFICANTLY 
  273. reduced.  The  fact the the grammars I supplied are free of %assoc and 
  274. %prec operators, implies the grammar  are  fairly  portable,  and  the 
  275. conflicts are open to peer code review (and not obscured).
  276.  
  277. Most  recently  I have joined the ANSI C++ committee (X3J16), and have 
  278. tried to follow their progress with hopes of maintaining compliance in 
  279. my grammar.  Unfortunately, political pressures within X3J16 appear to 
  280. make it IMHO more desirable to quickly approve a standard that matches 
  281. cfront's performance (when it is not dumping core), than to provide  a 
  282. clean,  consistent  and formal syntax as part of the standard.  Rather 
  283. than fixing inconsistent hackery within the syntax, there  is  IMHO  a 
  284. tendency   to  want  to  "hack  further"  to  match  cfront's  current 
  285. performance (or the ARM's prophesy).   As  an  example  of  this,  the 
  286. fundamental  hack  in  all of C is the feedback from the parser to the 
  287. lexer to identify typedefnames.  There is discussion afoot to (for  no 
  288. reason  other than compliance with a *proposed* cfront feature) extend 
  289. this another notch and require feedback to distinguish template names. 
  290. This hackery was not required by the syntax, rather it was "desirable" 
  291. to match the performance of beta-cfront (and the  ARM).   When  cfront 
  292. changes,  and  old  code is obsoleted, the arguments abound that it is 
  293. for the good of humanity.  When cfront is hacking inconsistently, then 
  294. no change can be made, because of the thousands of lines of code  that 
  295. depend  on this psuedo-standard.  Perhaps my grammar will help in some 
  296. small  way  Microsoft,  Zortech,  Borland,   and   dozens   of   other 
  297. entrepreneurs  work toward building a standard for a language that has 
  298. enough consistency to grow and flourish (note that none of  the  above 
  299. vendors  use  my grammar in their products, but I think they would all 
  300. share my desire for a cleaner syntax).  If I  am  successful  with  my 
  301. grammar,  then  I  will be able to write C++ tools in a consistent and 
  302. open marketplace.  From my perspective, the outcome is not clear.   If 
  303. you have a channel to support the use of a cleaner syntax in the X3J16 
  304. standard, I would heartily invite you to exercise that channel.
  305.  
  306. As  it  currently  stands,  my  grammar  teeters  on the edge of being 
  307. unusable due to its size.  The size in turn is due to the  variety  of 
  308. special cases that must be dealt with within C++ parsing.  With only a 
  309. few more inconsistent additions to the "standard language", my grammar 
  310. will surely become completely unusable.  I am trying to develop a yacc 
  311. preprocessor  that will allow me to rein back in the complexity of the 
  312. grammar.  If I can do this, then it will continue to  be  possible  to 
  313. update  my  grammar  to  match  the emerging ANSI Standard. I can only 
  314. promise to try.
  315.  
  316.  
  317. FEEDBACK ABOUT THE GRAMMARS
  318.  
  319. If you find any errors in my grammars, I would be  DELIGHTED  to  hear 
  320. mention  of  them!!!!   These  should  fall  into one of the following 
  321. categories:
  322.  
  323.         1) The grammar left out the following features of C++...
  324.         or
  325.         2) The grammar mis-parses the following sequences...
  326.         or
  327.         3) The discussion of the following ambiguity is
  328.         incorrect...
  329.         4) The grammar could be simplified as follows...
  330.  
  331. Please send  correspondence  of  this  form  to  jar@hq.ileaf.com.  My 
  332. response  to  1's  will be to add the feature (if possible!); feel sad 
  333. that I made a mistake; and feel glad that YOU found it.  I will have a 
  334. similar response to 2's.  Responses of type 3 are GREAT, but I haven't 
  335. found many folks that really get into YACC ambiguities, so I have  low 
  336. expectations...  feel free to surprise me!!! :-) :-).  Items of type 3 
  337. are interesting, but since simplicity is in the eye of  the  beholder, 
  338. such  suggestions  are  subject  to  debate.  I would be interested in 
  339. seeing suggestions in this area with the constraint that they  do  not 
  340. increase  the  number of conflicts in the grammar!  Please use YACC to 
  341. check your suggestions before submitting them. (It  is  often  AMAZING 
  342. how  the  slightest  change  in  the  grammar can change the number of 
  343. conflicts, and it took a great deal  of  work  to  reach  the  current 
  344. state).  Distribution site(s) will be set up to distribute updates and 
  345. or corrections.  Postings about the presence of  corrections  will  be 
  346. made on the net.
  347.  
  348. Since  the  two  grammars  (C and C++) were generated in parallel, you 
  349. should be able to compare non-terminals directly.  This will hopefully 
  350. make it easier to identify the  complexities  involved  with  the  C++ 
  351. grammar, and "ignore" those that result from standard ANSI C.  In both 
  352. cases  I  have  left the standard if-if-else ambiguity intact.  In the 
  353. case of ANSI C grammar, this is the only shift-reduce conflict in  the 
  354. grammar.  Although there are a number of conflicts in the C++ grammar, 
  355. there  are  actually  very  few  classes  of  problems.  In  order  to 
  356. disambiguate the C++ grammar enough that YACC can figure out  what  to 
  357. do,  I  was  commonly forced to "inline expand" non-terminals found in 
  358. the C grammar.  This expansion allowed YACC  to  defer  disambiguation 
  359. until  it  was possible for an LR(1) parser to understand the context. 
  360. The unfortunate consequence of this inline expansion is a large growth 
  361. in the number of rules, and the presence of an effective  "multiplier" 
  362. in  most  cases  where  conflicts do occur. As a result, any conflicts 
  363. that arise are multiplied by a factor corresponding to the  number  of 
  364. rules  I  had  to  list  separately.   I  have grouped the C++ grammar 
  365. conflicts in the "Status" section of the GRAMMAR5.TXT paper,  but  you 
  366. are welcome to explore my grammars using YACC directly (be warned that 
  367. you  will  need  a  robust  version  of  YACC  to handle the C++ sized 
  368. grammar).  PLEASE do not be put off by the number of conflicts in  the 
  369. C++  grammar.  There are VERY FEW CONFLICTS, but my elaborated grammar 
  370. confuses the count.
  371.  
  372. The GRAMMAR5.TXT paper is FAR from a publishable quality paper, but it 
  373. discusses many of the issues involved in ambiguities  in  my  grammar, 
  374. and  more  generally  in the C++ language. I hope GRAMMAR5.TXT it is a 
  375. vast improvement over "nothing at all", but apologize in  advance  for 
  376. lack of polished structure, and the presence of many typos (which must 
  377. surely be present).  I hope you find this almost-paper interesting. My 
  378. attempts   at  documenting  conflicts  have  certainly  clarified  the 
  379. problems in my mind. Based on my experience with the conflicts I  have 
  380. identified,  most  current  compilers  and translator fall prey to the 
  381. situations that I have uncovered.  I hope that other  compilers,  that 
  382. do  not  make  use of the grammar I have made available, will at least 
  383. seek to standardize the resolution of the problems identified.
  384.  
  385.  
  386. The AUTODOC5.TXT file provides interesting reading  for  both  readers 
  387. interested  in  LR  and  LALR  parsing (and the subtle connections and 
  388. distinctions between them), as well as any user that wishes  to  fully 
  389. comprehend  the  contents  of  the  Y.OUTPUT  file.   It  includes  an 
  390. extensive  discussion  of  ambiguities,  how  they  are  removed,  how 
  391. LALR-only ambiguities arise, and how they can be dealt with.
  392.  
  393. With  this  release  of the grammar I have begun to distribute machine 
  394. generated documentation for my grammar.  As a result, if  my  analysis 
  395. of  conflicts  are  questionable,  the  supporting data is immediately 
  396. present to confirm or deny my analysis.  If you wish to correct any of 
  397. my analysis, please use and refer to the Y.OUTPUT  file  that  I  have 
  398. provided. 
  399.  
  400. As  a  small  commercial message... I am a freelance consultant, and I 
  401. travel far and wide to perform contracts.  If you like the work that I 
  402. am presenting in this group of documents, and  would  like  to  see  a 
  403. resume or at least talk, please feel free to contact me.
  404.  
  405. I  hope  that  the  grammars  that  I have provided, will lead to many 
  406. successful C++ processing projects.
  407.  
  408. Jim Roskind 
  409. Independent Consultant 
  410. 516 Latania Palm Drive  
  411. Indialantic FL 32903 
  412. (407)729-4348 
  413. jar@hq.ileaf.com or ...!uunet!leafusa!jar
  414.